package com.maiji.cloud.service.impl;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.maiji.cloud.microservice.UserInfoService;
import com.maiji.cloud.response.shopingmall.*;
import com.maiji.cloud.service.CapitalMainService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import com.alibaba.fastjson.JSON;
import com.maiji.cloud.config.MyRedisConfig;
import com.maiji.cloud.entities.login.AppUser;
import com.maiji.cloud.entities.shopingmall.CapitalMain;
import com.maiji.cloud.entities.shopingmall.CapitalMainLog;
import com.maiji.cloud.entities.shopingmall.DiscountCoupon;
import com.maiji.cloud.entities.shopingmall.ExchangeLog;
import com.maiji.cloud.mapper.CapitalMainLogMapper;
import com.maiji.cloud.mapper.CapitalMainMapper;
import com.maiji.cloud.mapper.DiscountCouponMapper;
import com.maiji.cloud.mapper.ExchangeLogMapper;
import com.maiji.cloud.mapper.GoodsMapper;
import com.maiji.cloud.request.BaseDataReqDto;
import com.maiji.cloud.request.shopingmall.AddExchangeLogReqDto;
import com.maiji.cloud.request.shopingmall.GetExchangeLogReqDto;
import com.maiji.cloud.response.BaseDataResDto;
import com.maiji.cloud.response.BaseResDto;
import com.maiji.cloud.response.Status;
import com.maiji.cloud.service.CouponsService;
import com.maiji.cloud.utils.CommonIntValueEnum;
import com.maiji.cloud.utils.FlowTypeEnum;
import com.maiji.cloud.utils.RedisUtil;
import com.maiji.cloud.utils.UUID_MD5;

/**
 * 优惠券 Description:
 * 
 * @author zhanglr
 * @date 2019年6月24日
 */
@Service
@Transactional
public class CouponsServiceImpl extends ServiceImpl<DiscountCouponMapper, DiscountCoupon> implements CouponsService {

	Logger logger = LoggerFactory.getLogger(CouponsServiceImpl.class);
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;
    @Autowired
    private UserInfoService userInfoService;
	@Autowired
	private DiscountCouponMapper discountCouponMapper;
	@Autowired
	private ExchangeLogMapper exchangeLogMapper;
	@Autowired
	private GoodsMapper goodsMapper;
	@Autowired
	private CapitalMainMapper capitalMainMapper;
	@Autowired
	private CapitalMainService capitalMainService;
	
	@Autowired
	private CapitalMainLogMapper capitalMainLogMapper;
	

	@Override
	public GetDiscountCouponListResDto getDiscountCouponList() {
		List<DiscountCoupon> discountCouponList = discountCouponMapper.selectDiscountCouponList(new Date(), null,
				CommonIntValueEnum.DISCOUNT_COUPON_TYPE_EXCHANGE.getValue());

		List<GetDiscountCouponListResData> list = new ArrayList<GetDiscountCouponListResData>();

		for (DiscountCoupon discountCoupon : discountCouponList) {
			GetDiscountCouponListResData getDiscountCouponListResData = new GetDiscountCouponListResData();
			BeanUtils.copyProperties(discountCoupon, getDiscountCouponListResData);
			list.add(getDiscountCouponListResData);
		}

		GetDiscountCouponListResDto GetDiscountCouponListResDto = new GetDiscountCouponListResDto(Status.SUCCESS);

		return GetDiscountCouponListResDto.setData(list);
	}

	@Override
	public GetExchangeLogResDto getExchangeLogList(GetExchangeLogReqDto getExchangeLogReqDto) {
		logger.info("CouponsServiceImpl.getExchangeLogList,param is {}", JSON.toJSONString(getExchangeLogReqDto));
		AppUser appUser = RedisUtil.getAppUserByRedis(redisTemplate, MyRedisConfig.REDISDATABASENO,
				getExchangeLogReqDto.getMaijiToken(), userInfoService);
		if (appUser == null) {
			logger.info("GetExchangeLogResDto.getExchangeLogList,appUser is {}", JSON.toJSONString(appUser));
			BaseResDto.baseResDto(Status.PARAMETERERROR, "token 无效 ");
		}
		Integer start = (getExchangeLogReqDto.getPage() - 1) * getExchangeLogReqDto.getSize();
		List<ExchangeLog> listExchangeLog = exchangeLogMapper.selectListByUserId(appUser.getUuId(), CommonIntValueEnum.EXCHANGELOG_TYPE_SHOPING.getValue(),start,
				getExchangeLogReqDto.getSize());

		List<GetExchangeLogResData> list = new ArrayList<GetExchangeLogResData>();
		for (ExchangeLog exchangeLog : listExchangeLog) {
			GetExchangeLogResData getExchangeLogResData = new GetExchangeLogResData();
			BeanUtils.copyProperties(exchangeLog, getExchangeLogResData);
			list.add(getExchangeLogResData);
		}
		GetExchangeLogResDto getExchangeLogResDto = new GetExchangeLogResDto(Status.SUCCESS);
		getExchangeLogResDto.setData(list);
		return getExchangeLogResDto;
	}

	@Override
	@Transactional(isolation = Isolation.READ_UNCOMMITTED)
	public BaseDataResDto addExchangeLog(AddExchangeLogReqDto param) {
		logger.info("CouponsServiceImpl.addExchangeLog,param is {}", JSON.toJSONString(param));
		AppUser appUser = RedisUtil.getAppUserByRedis(redisTemplate, MyRedisConfig.REDISDATABASENO, param.getMaijiToken(), userInfoService);

		if (appUser == null) {
			logger.info("CouponsServiceImpl.addExchangeLog,appUser is {}", JSON.toJSONString(appUser));
			return new BaseDataResDto(Status.PARAMETERERROR, "token 无效 ");
		}

		// 获取用户资金
		CapitalMain capitalMain = capitalMainMapper.selectOneByUserId(appUser.getUuId());
		if (capitalMain == null){

			capitalMainService.createCapitalMain(appUser.getUuId());
		}
		if (capitalMain == null) {
			return new BaseDataResDto(Status.PARAMETERERROR, "暂无积分数据");
		}
		// 积分
		Integer newIntegral = null;

		ExchangeLog exchangeLog = new ExchangeLog();
		
		CapitalMainLog capitalMainLog = new CapitalMainLog();
		// 优惠券
		if (CommonIntValueEnum.EXCHANGELOG_TYPE_COUPON.getValue() == param.getData().getType()) {
			DiscountCoupon discountCoupon = discountCouponMapper.selectById(param.getData().getDiscountCoupon());

			if (discountCoupon == null) {
				logger.info("CouponsServiceImpl.addExchangeLog,优惠券id无效,id is {}", param.getData().getDiscountCoupon());
				return new BaseDataResDto(Status.PARAMETERERROR, "不存在的优惠券 ");
			}
			if (discountCoupon.getType() != CommonIntValueEnum.DISCOUNT_COUPON_TYPE_FREE.getValue()
					&& discountCoupon.getType() != CommonIntValueEnum.DISCOUNT_COUPON_TYPE_EXCHANGE.getValue()) {
				return new BaseDataResDto(Status.PARAMETERERROR, "无效优惠券 ");
			}
			// 领取免费优惠券
			if (discountCoupon.getType() == CommonIntValueEnum.DISCOUNT_COUPON_TYPE_FREE.getValue()) {
				BeanUtils.copyProperties(discountCoupon, exchangeLog);
				exchangeLog.setUuId(UUID_MD5.getUUID());
				exchangeLog.setUserId(appUser.getUuId());
				exchangeLog.setDiscountCoupon(discountCoupon.getUuId());
				exchangeLog.setType(CommonIntValueEnum.EXCHANGELOG_TYPE_COUPON.getValue());
				exchangeLog.setDiscountCouponType(CommonIntValueEnum.DISCOUNT_COUPON_TYPE_FREE.getValue());
				exchangeLogMapper.insertOne(exchangeLog);
				discountCoupon.setAmount(discountCoupon.getAmount() - 1);
				if (discountCouponMapper.updateAllColumnById(discountCoupon) <= 0) {
					logger.info("CouponsServiceImpl.addExchangeLog,param is {},递归调用", JSON.toJSONString(param));
					addExchangeLog(param);
				}
				return new BaseDataResDto(Status.SUCCESS);
			}
			discountCoupon.setAmount(discountCoupon.getAmount() - 1);
			if (discountCouponMapper.updateAllColumnById(discountCoupon) <= 0) {
				logger.info("CouponsServiceImpl.addExchangeLog,param is {},递归调用", JSON.toJSONString(param));
				addExchangeLog(param);
			}

			BeanUtils.copyProperties(discountCoupon, exchangeLog);
			exchangeLog.setDiscountCoupon(discountCoupon.getUuId());
			exchangeLog.setType(CommonIntValueEnum.EXCHANGELOG_TYPE_COUPON.getValue());

			newIntegral = capitalMain.getIntegral() - discountCoupon.getIntegral();
			capitalMainLog.setChangeQuantity(discountCoupon.getIntegral()+0.0);

		}

		// 兑换商品
		if (CommonIntValueEnum.EXCHANGELOG_TYPE_SHOPING.getValue() == param.getData().getType()) {
			GoodsResData goods = goodsMapper.findGoodsById(param.getData().getDiscountCoupon());
			exchangeLog.setType(CommonIntValueEnum.EXCHANGELOG_TYPE_SHOPING.getValue());
			exchangeLog.setGoodName(goods.getName());
			exchangeLog.setDiscountCoupon(goods.getUuId());
			exchangeLog.setIntegral(goods.getIntegral());
			exchangeLog.setOrderId(param.getData().getOrderId());
			exchangeLog.setNum(param.getData().getNum());
			newIntegral = capitalMain.getIntegral() - (goods.getIntegral() * param.getData().getNum());
			
			capitalMainLog.setChangeQuantity(goods.getIntegral() * param.getData().getNum()+0.0);
		}

		if (newIntegral < 0) {
			logger.info("CouponsServiceImpl.addExchangeLog,newIntegral", newIntegral);
			return new BaseDataResDto(Status.PARAMETERERROR, "剩余积分不足");
		}
		
		//capitalMain.setIntegral(newIntegral);
		exchangeLog.setDiscountCouponType(CommonIntValueEnum.DISCOUNT_COUPON_TYPE_EXCHANGE.getValue());
		exchangeLog.setUuId(UUID_MD5.getUUID());
		exchangeLog.setUserId(appUser.getUuId());
		exchangeLogMapper.insertOne(exchangeLog);
		
		//修改资金增加流水
		Boolean bool = capitalMainService.updateCapitalMain(appUser.getUuId(), FlowTypeEnum.INTEGRAL, capitalMainLog.getChangeQuantity()+"", FlowTypeEnum.DECREASE, FlowTypeEnum.EXCHANGE_GOODS, exchangeLog.getUuId());
		if(bool) {
			new BaseDataResDto(Status.SUCCESS);	
		}
		
		return new BaseDataResDto(Status.ERROR);
	}

	@Override
	public BaseDataResDto<List<GetDiscountCouponListResData>> getUsableDiscountCouponList(Double money, String maijiToken) {
		AppUser appUser = RedisUtil.getAppUserByRedis(redisTemplate, MyRedisConfig.REDISDATABASENO, maijiToken, userInfoService);

		if (appUser == null) {
			logger.info("CouponsServiceImpl.getUsableDiscountCouponList,appUser is {}", JSON.toJSONString(appUser));
			return new BaseDataResDto<List<GetDiscountCouponListResData>>(Status.PARAMETERERROR, "token 无效 ");
		}
		
		// 免费所有的领取优惠券
		List<ExchangeLog> listFreeExchangeLog = exchangeLogMapper.getUsableDiscountCouponList(new Date(), null,
				appUser.getUuId(), CommonIntValueEnum.DISCOUNT_COUPON_TYPE_FREE.getValue());

		List<GetDiscountCouponListResData> getDiscountCouponList = listFreeExchangeLog.stream().map(exchangeLog -> {
			GetDiscountCouponListResData getDiscountCouponListResData = new GetDiscountCouponListResData();
			BeanUtils.copyProperties(exchangeLog, getDiscountCouponListResData);
			getDiscountCouponListResData.setIsUse(0);
			getDiscountCouponListResData.setDiscountCouponId(exchangeLog.getDiscountCoupon());
			getDiscountCouponListResData.setExchangeId(exchangeLog.getUuId());
			DiscountCoupon discountCoupon = discountCouponMapper.selectById(exchangeLog.getDiscountCoupon());
			getDiscountCouponListResData.setMoney(discountCoupon.getMoney());
			getDiscountCouponListResData.setStartTime(discountCoupon.getStartTime());
			getDiscountCouponListResData.setEndTime(discountCoupon.getEndTime());

			return getDiscountCouponListResData;
		}).collect(Collectors.toList());

		if (money == null) {
			BaseDataResDto<List<GetDiscountCouponListResData>> baseDataResDto = new BaseDataResDto<List<GetDiscountCouponListResData>>(
					Status.SUCCESS);
			baseDataResDto.setData(getDiscountCouponList);

			return baseDataResDto;
		}
		// 筛选出符合价格并且当前时间点可用的的优惠券
		List<ExchangeLog> listFreeExchangeLogTwo = exchangeLogMapper.getUsableDiscountCouponListByTime(new Date(),
				money, appUser.getUuId(), CommonIntValueEnum.DISCOUNT_COUPON_TYPE_FREE.getValue());

		List<GetDiscountCouponListResData> getDiscountCouponListTwo = listFreeExchangeLogTwo.stream()
				.map(exchangeLog -> {
					GetDiscountCouponListResData getDiscountCouponListResData = new GetDiscountCouponListResData();
					BeanUtils.copyProperties(exchangeLog, getDiscountCouponListResData);
					getDiscountCouponListResData.setIsUse(0);
					getDiscountCouponListResData.setExchangeId(exchangeLog.getUuId());
					getDiscountCouponListResData.setDiscountCouponId(exchangeLog.getDiscountCoupon());
					DiscountCoupon discountCoupon = discountCouponMapper.selectById(exchangeLog.getDiscountCoupon());
					getDiscountCouponListResData.setMoney(discountCoupon.getMoney());
					getDiscountCouponListResData.setStartTime(discountCoupon.getStartTime());
					getDiscountCouponListResData.setEndTime(discountCoupon.getEndTime());
					return getDiscountCouponListResData;
				}).collect(Collectors.toList());
		// 不可用
		List<GetDiscountCouponListResData> twoGetDiscountCouponListResData = new ArrayList<GetDiscountCouponListResData>();

		// 从领取的优惠券列表筛选出不可用的
		for (GetDiscountCouponListResData getDiscountCouponListResData : getDiscountCouponList) {
			int type = 0;
			for (GetDiscountCouponListResData discountCouponListResDataTwo : getDiscountCouponListTwo) {
				if (getDiscountCouponListResData.getExchangeId().equals(discountCouponListResDataTwo.getExchangeId())) {
					type++;
				}
			}
			if (type == 0) {
				getDiscountCouponListResData.setIsUse(1);
				twoGetDiscountCouponListResData.add(getDiscountCouponListResData);
			}
		}

		List<GetDiscountCouponListResData> list = new ArrayList<GetDiscountCouponListResData>();

		list.addAll(getDiscountCouponListTwo);
		list.addAll(twoGetDiscountCouponListResData);

		BaseDataResDto<List<GetDiscountCouponListResData>> baseDataResDto = new BaseDataResDto<List<GetDiscountCouponListResData>>(
				Status.SUCCESS);
		baseDataResDto.setData(list);

		return baseDataResDto;
	}

	public Date getNextDate(Date date, Integer type, Integer num) {
		Calendar calendar = Calendar.getInstance();
		calendar.setTime(date);
		switch (type) {
		case 1:
			calendar.add(Calendar.YEAR, +num);// +1今天的时间加一年
			break;
		case 2:
			calendar.add(Calendar.MONTH, +num);// +1今天的时间加一月
			break;
		case 3:
			calendar.add(Calendar.DATE, +num);// +1今天的时间加一天
			break;

		default:
			calendar.add(Calendar.DATE, +0);// +1今天的时间加一天
			break;
		}
		date = calendar.getTime();
		return date;
	}

	@Override
	public FreeDiscountCouponListResDto getfreeDiscountCouponList(Double money) {

		List<FreeDiscountCouponListResData> listFreeDiscountCouponListResData = new ArrayList<FreeDiscountCouponListResData>();

		// 获取所有免费领取优惠券列表
		List<DiscountCoupon> listDiscountCoupon = discountCouponMapper.selectDiscountCouponList(new Date(), null,
				CommonIntValueEnum.DISCOUNT_COUPON_TYPE_FREE.getValue());

		for (DiscountCoupon discountCoupon : listDiscountCoupon) {
			FreeDiscountCouponListResData freeDiscountCouponListResData = new FreeDiscountCouponListResData();
			BeanUtils.copyProperties(discountCoupon, freeDiscountCouponListResData);
			listFreeDiscountCouponListResData.add(freeDiscountCouponListResData);

		}
		if (money == null) {
			FreeDiscountCouponListResDto freeDiscountCouponListResDto = new FreeDiscountCouponListResDto(Status.SUCCESS,
					"请求成功");
			freeDiscountCouponListResDto.setData(listFreeDiscountCouponListResData);

			return freeDiscountCouponListResDto;
		}
		// 获取符合条件免费领取优惠券列表
		List<DiscountCoupon> listDiscountCouponTwo = discountCouponMapper.selectDiscountCouponList(new Date(), money,
				CommonIntValueEnum.DISCOUNT_COUPON_TYPE_FREE.getValue());

		List<FreeDiscountCouponListResData> getDiscountCouponListTwo = listDiscountCouponTwo.stream()
				.map(discountCoupon -> {
					FreeDiscountCouponListResData freeDiscountCouponListResData = new FreeDiscountCouponListResData();
					BeanUtils.copyProperties(discountCoupon, freeDiscountCouponListResData);
					freeDiscountCouponListResData.setIsUse(0);
					return freeDiscountCouponListResData;
				}).collect(Collectors.toList());

		List<FreeDiscountCouponListResData> result = listFreeDiscountCouponListResData.stream()
				.filter(freeDiscountCouponListResData -> money < freeDiscountCouponListResData.getMoney())
				.map(newFreeDiscountCouponListResData -> {
					newFreeDiscountCouponListResData.setIsUse(1);
					return newFreeDiscountCouponListResData;
				}).collect(Collectors.toList());

		FreeDiscountCouponListResDto freeDiscountCouponListResDto = new FreeDiscountCouponListResDto(Status.SUCCESS,
				"请求成功");

		List<FreeDiscountCouponListResData> list = new ArrayList<>();
		list.addAll(getDiscountCouponListTwo);
		list.addAll(result);

		freeDiscountCouponListResDto.setData(list);

		return freeDiscountCouponListResDto;
	}

	@Override
	public BaseDataResDto<List<GetDiscountCouponListResData>> noPossessDiscountCouponList(Double money,
			String maijiToken) {
		
		AppUser appUser = RedisUtil.getAppUserByRedis(redisTemplate, MyRedisConfig.REDISDATABASENO, maijiToken, userInfoService);

		if (appUser == null) {
			logger.info("CouponsServiceImpl.noPossessDiscountCouponList,param is {}", maijiToken);
			return new BaseDataResDto<List<GetDiscountCouponListResData>>(Status.PARAMETERERROR, "token 无效 ");
		}
		
		// 获取符合条件免费领取优惠券列表
		List<DiscountCoupon> listDiscountCouponTwo = discountCouponMapper.selectDiscountCouponListByTime(new Date(),
				null, CommonIntValueEnum.DISCOUNT_COUPON_TYPE_FREE.getValue());

		List<GetDiscountCouponListResData> getDiscountCouponListTwo = listDiscountCouponTwo.stream()
				.map(discountCoupon -> {
					GetDiscountCouponListResData getDiscountCouponListResData = new GetDiscountCouponListResData();
					BeanUtils.copyProperties(discountCoupon, getDiscountCouponListResData);
					getDiscountCouponListResData.setIsUse(0);
					getDiscountCouponListResData.setDiscountCouponId(discountCoupon.getUuId());
					return getDiscountCouponListResData;
				}).collect(Collectors.toList());

		List<GetDiscountCouponListResData> noPossess = new ArrayList<GetDiscountCouponListResData>();

		BaseDataResDto<List<GetDiscountCouponListResData>> listResDate = new BaseDataResDto<List<GetDiscountCouponListResData>>(
				Status.SUCCESS);

		// 筛选出已经领取的的优惠券
		List<String> listFreeExchangeLogTwo = exchangeLogMapper.getDiscountCouponList(new Date(), null,
				appUser.getUuId(), CommonIntValueEnum.DISCOUNT_COUPON_TYPE_FREE.getValue());
		loop1: for (GetDiscountCouponListResData getDiscountCouponListResData : getDiscountCouponListTwo) {
			for (String str : listFreeExchangeLogTwo) {
				if (getDiscountCouponListResData.getDiscountCouponId().equals(str)) {
					continue loop1;
				}
			}
			noPossess.add(getDiscountCouponListResData);

		}

		listResDate.setData(noPossess);

		return listResDate;
	}

	@Override
	public GetDiscountCouponListResData checkCouponUseable(Double money, String exchangeId, String token) {
		BaseDataResDto<List<GetDiscountCouponListResData>> usableDiscountCouponListData = getUsableDiscountCouponList(money, token);
		List<GetDiscountCouponListResData> couponList = usableDiscountCouponListData.getData().stream()
				.filter(c -> c.getExchangeId() != null && c.getExchangeId().equals(exchangeId) && c.getIsUse() == 0)
				.collect(Collectors.toList());
		return couponList.size() == 0 ? null : couponList.get(0);
	}

	@Override
	public BaseDataResDto<List<HaveDiscountCouponListResData>> getHaveDiscountCouponList(BaseDataReqDto<Integer> param,
			String maijiToken) {
		logger.info("CouponsServiceImpl.getHaveDiscountCouponList,param is {}，maijiToken is {}", JSON.toJSONString(param), maijiToken);
		AppUser appUser = RedisUtil.getAppUserByRedis(redisTemplate, MyRedisConfig.REDISDATABASENO, maijiToken, userInfoService);

		if (appUser == null) {
			logger.info("CouponsServiceImpl.getHaveDiscountCouponList,param is {}，maijiToken is {}", JSON.toJSONString(param), maijiToken);
			return new BaseDataResDto<List<HaveDiscountCouponListResData>>(Status.PARAMETERERROR);
		}
		Integer type = param.getData();
		Integer start = (param.getMetaData().getPage() - 1 ) * param.getMetaData().getSize();
		List<ExchangeLog> exchangeLogList = exchangeLogMapper.getHaveDiscountCouponList(new Date(),appUser.getUuId(),type,start,param.getMetaData().getSize());
		BaseDataResDto<List<HaveDiscountCouponListResData>> baseDataResDto = new BaseDataResDto<List<HaveDiscountCouponListResData>>(Status.SUCCESS);
		
		List<HaveDiscountCouponListResData> list = new ArrayList<HaveDiscountCouponListResData>();
		for(ExchangeLog exchangeLog : exchangeLogList) {
			HaveDiscountCouponListResData haveDiscountCouponListResData = new HaveDiscountCouponListResData();
			BeanUtils.copyProperties(exchangeLog, haveDiscountCouponListResData);
			haveDiscountCouponListResData.setDiscountCouponId(exchangeLog.getDiscountCoupon());
			haveDiscountCouponListResData.setExchangeId(exchangeLog.getUuId());
			DiscountCoupon discountCoupon = discountCouponMapper.selectById(exchangeLog.getDiscountCoupon());
			haveDiscountCouponListResData.setMoney(discountCoupon.getMoney());
			haveDiscountCouponListResData.setStartTime(discountCoupon.getStartTime());
			haveDiscountCouponListResData.setEndTime(discountCoupon.getEndTime());
			list.add(haveDiscountCouponListResData);
		}
		baseDataResDto.setData(list);
		return baseDataResDto;
	}

}
